
package com.zcp.pcsuitall.business;

import com.zcp.org.apache.commons.codec.binary.Base64;
import com.zcp.pcsuitall.Action;
import com.zcp.pcsuitall.BusinessControl;
import com.zcp.pcsuitall.IDealWithMessage;
import com.zcp.pcsuitall.R;
import com.zcp.pcsuitall.XmlDataDealWith;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;

import android.accounts.Account;
import android.content.ContentProviderOperation;
import android.content.ContentProviderOperation.Builder;
import android.content.ContentProviderResult;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Event;
import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
import android.provider.ContactsContract.CommonDataKinds.Im;
import android.provider.ContactsContract.CommonDataKinds.Nickname;
import android.provider.ContactsContract.CommonDataKinds.Note;
import android.provider.ContactsContract.CommonDataKinds.Organization;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.provider.ContactsContract.CommonDataKinds.Relation;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.provider.ContactsContract.CommonDataKinds.Website;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.Groups;
import android.provider.ContactsContract.RawContacts;
import android.telephony.TelephonyManager;
import android.util.Xml;

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

public class ContactsManager implements IDealWithMessage {

    public static final String TAG = "ContactsManager";

    // 手机内的账户，只包含与联系人相关的账户
    private ArrayList<Account> accounts;

    public ContactsManager() {
        initCommonkind();

    }

    private static final void initColumnMap() {
        phoneColumnsMap = createColumnMap(phoneTags, phoneColumns);
        emailColumnsMap = createColumnMap(emailTags, emailColumns);
        imColumnsMap = createColumnMap(imTags, imColumns);
        eventColumnsMap = createColumnMap(eventTags, eventColumns);
        organizationColumnsMap = createColumnMap(organizationTags, organizationColumns);
        groupMemberColumnsMap = createColumnMap(groupMemberTags, groupMemberColumns);
        structuredPostalColumnsMap = createColumnMap(structuredPostalTags, structuredPostalColumns);
        relationColumnsMap = createColumnMap(relationTags, relationColumns);
        websiteColumnsMap = createColumnMap(websiteTags, websiteColumns);
        nicknameColumnsMap = createColumnMap(nicknameTags, nicknameColumns);

    }

    private static HashMap<String, String> phoneColumnsMap;

    private static HashMap<String, String> emailColumnsMap;

    private static HashMap<String, String> imColumnsMap;

    private static HashMap<String, String> eventColumnsMap;

    private static HashMap<String, String> organizationColumnsMap;

    private static HashMap<String, String> groupMemberColumnsMap;

    private static HashMap<String, String> structuredPostalColumnsMap;

    private static HashMap<String, String> relationColumnsMap;

    private static HashMap<String, String> websiteColumnsMap;

    private static HashMap<String, String> nicknameColumnsMap;

    // SIM账户的账户名，c_contact为cdma的账户名
    private static final String[] simNames = new String[] {
            "SIM", "c_contact"
    };

    // SIM账户的账户类型,com.card.contacts为cdma的账户类型
    private static final String[] simTypes = new String[] {
            "com.anddroid.contacts.sim", "com.card.contacts"
    };

    // rawContact的ContentProviderOperation构建器
    private static Builder rawcpoBuilder = null;

    // commondatakinds的ContentProviderOperation构建器
    private static Builder cpoBuilder = null;

    private static final ArrayList<ContentProviderOperation> mAddContactOps = new ArrayList<ContentProviderOperation>();

    private static final String[] commonkinds = new String[] {
            "phone", "email", "im", "event", "organization", "groupMember", "structuredPostal",
            "relation", "website", "nickname"
    };

    private static final String[] groupProjection = new String[] {
            Groups._ID, Groups.TITLE
    };

    private static final String[] groupSummaryProjection = new String[] {
        Groups.SUMMARY_COUNT
    };

    private static final HashMap<String, String> commonkindMimeTypeMap = new HashMap<String, String>();

    private static final HashMap<String, HashMap<String, String>> commonkindColumnMap = new HashMap<String, HashMap<String, String>>();

    private static final void initCommonkind() {
        initColumnMap();

        commonkindMimeTypeMap.put(commonkinds[0], Phone.CONTENT_ITEM_TYPE);
        commonkindMimeTypeMap.put(commonkinds[1], Email.CONTENT_ITEM_TYPE);
        commonkindMimeTypeMap.put(commonkinds[2], Im.CONTENT_ITEM_TYPE);
        commonkindMimeTypeMap.put(commonkinds[3], Event.CONTENT_ITEM_TYPE);
        commonkindMimeTypeMap.put(commonkinds[4], Organization.CONTENT_ITEM_TYPE);
        commonkindMimeTypeMap.put(commonkinds[5], GroupMembership.CONTENT_ITEM_TYPE);
        commonkindMimeTypeMap.put(commonkinds[6], StructuredPostal.CONTENT_ITEM_TYPE);
        commonkindMimeTypeMap.put(commonkinds[7], Relation.CONTENT_ITEM_TYPE);
        commonkindMimeTypeMap.put(commonkinds[8], Website.CONTENT_ITEM_TYPE);
        commonkindMimeTypeMap.put(commonkinds[9], Nickname.CONTENT_ITEM_TYPE);

        commonkindColumnMap.put(commonkinds[0], phoneColumnsMap);
        commonkindColumnMap.put(commonkinds[1], emailColumnsMap);
        commonkindColumnMap.put(commonkinds[2], imColumnsMap);
        commonkindColumnMap.put(commonkinds[3], eventColumnsMap);
        commonkindColumnMap.put(commonkinds[4], organizationColumnsMap);
        commonkindColumnMap.put(commonkinds[5], groupMemberColumnsMap);
        commonkindColumnMap.put(commonkinds[6], structuredPostalColumnsMap);
        commonkindColumnMap.put(commonkinds[7], relationColumnsMap);
        commonkindColumnMap.put(commonkinds[8], websiteColumnsMap);
        commonkindColumnMap.put(commonkinds[9], nicknameColumnsMap);
    }

    @Override
    public boolean dealWith(SocketChannel sc, Action action, Context context) {
        boolean success = false;
        if (action != null) {
            String op = action.getName();
            if ("LoadContact".equals(op)) {
                success = loadContactHandler(sc, action, context);
            } else if ("AddContact".equals(op)) {
                success = addContactHandler(sc, action, context);
            } else if ("DeleteContact".equals(op)) {
                success = deleteContactOrGroupHandler(sc, action, context, RawContacts.CONTENT_URI);
            } else if ("ReadContactCapacity".equals(op)) {
                success = readContactCapactiyHandler(sc, action, context);
            } else if ("CleanupContact".equals(op)) {
                success = cleanupContactHandler(sc, action, context);
            } else if ("ReadContactTotal".equals(op)) {
                success = readContactTotalHandler(sc, action, context);
            } else if ("ModifyContact".equals(op)) {
                success = modifyContactHandler(sc, action, context);
            } else if ("LoadContactGroup".equals(op)) {
                success = loadContactGroupHandler(sc, action, context);
            } else if ("AddContactGroup".equals(op)) {
                success = addContactGroupHandler(sc, action, context);
            } else if ("ModifyContactGroup".equals(op)) {
                success = modifyContactGroupHandler(sc, action, context);
            } else if ("DeleteContactGroup".equals(op)) {
                success = deleteContactOrGroupHandler(sc, action, context, Groups.CONTENT_URI);
            }
        }
        return success;
    }

    /**
     * 修改联系人
     * 
     * @param sc
     * @param action
     * @param context
     * @return
     */
    private boolean modifyContactHandler(SocketChannel sc, Action action, Context context) {
        ContentResolver resolver = context.getContentResolver();
        String source = action.getSource();
        StringReader sr = new StringReader(source);
        int rawIndex = 0;
        XmlPullParser parser = Xml.newPullParser();
        String rawContactId = null;
        try {
            parser.setInput(sr);
            int event = parser.getEventType();
            while (event != XmlPullParser.END_DOCUMENT) {
                switch (event) {
                    case XmlPullParser.START_TAG:
                        if (parser.isEmptyElementTag()) {
                            if ("id".equalsIgnoreCase(parser.getName().trim())) {
                                BusinessControl.returnToClient(sc, XmlDataDealWith.getErrorString(
                                        action.getName(), "4",
                                        context.getResources().getString(R.string.paramIsNull_4)),
                                        context);
                                return false;
                            }
                            break;
                        }
                        if ("item".equals(parser.getName()) && parser.getDepth() == 3) {
                            rawIndex = mAddContactOps.size();
                            if (rawIndex >= 300) {
                                resolver.applyBatch(ContactsContract.AUTHORITY, mAddContactOps);
                                mAddContactOps.clear();
                                rawIndex = 0;
                            }
                            rawcpoBuilder = ContentProviderOperation
                                    .newUpdate(RawContacts.CONTENT_URI);
                        } else if ("id".equalsIgnoreCase(parser.getName())) {
                            rawContactId = parser.nextText();
                            rawcpoBuilder
                                    .withSelection(RawContacts._ID + "= " + rawContactId, null);
                            resolver.delete(ContactsContract.Data.CONTENT_URI,
                                    ContactsContract.Data.RAW_CONTACT_ID + " = " + rawContactId,
                                    null);

                        } else if ("source_id".equalsIgnoreCase(parser.getName())) {
                            rawcpoBuilder.withValue(RawContacts.SOURCE_ID, parser.nextText());

                        } else if ("last_contact".equalsIgnoreCase(parser.getName())) {
                            rawcpoBuilder.withValue(RawContacts.LAST_TIME_CONTACTED,
                                    parser.nextText());
                        } else if ("starred".equalsIgnoreCase(parser.getName())) {
                            rawcpoBuilder.withValue(RawContacts.STARRED, parser.nextText());
                        } else if ("account_name".equalsIgnoreCase(parser.getName())) {
                            String accountName = parser.nextText();
                            rawcpoBuilder.withValue(RawContacts.ACCOUNT_NAME, accountName);

                        } else if ("account_type".equalsIgnoreCase(parser.getName())) {
                            String accountType = parser.nextText();
                            rawcpoBuilder.withValue(RawContacts.ACCOUNT_TYPE, accountType);

                        } else if ("structuredName".equalsIgnoreCase(parser.getName())) {
                            cpoBuilder = ContentProviderOperation
                                    .newInsert(ContactsContract.Data.CONTENT_URI)
                                    .withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactId)
                                    .withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);

                            while (!(event == XmlPullParser.END_TAG && "structuredName"
                                    .equals(parser.getName()))) {
                                switch (event) {
                                    case XmlPullParser.START_TAG:
                                        if ("display_name".equalsIgnoreCase(parser.getName())) {
                                            cpoBuilder.withValue(StructuredName.DISPLAY_NAME,
                                                    parser.nextText());
                                        } else if ("given_name".equalsIgnoreCase(parser.getName())) {
                                            cpoBuilder.withValue(StructuredName.GIVEN_NAME,
                                                    parser.nextText());
                                        } else if ("family_name".equalsIgnoreCase(parser.getName())) {
                                            cpoBuilder.withValue(StructuredName.FAMILY_NAME,
                                                    parser.nextText());
                                        } else if ("middle_name".equalsIgnoreCase(parser.getName())) {
                                            cpoBuilder.withValue(StructuredName.MIDDLE_NAME,
                                                    parser.nextText());
                                        }
                                        break;
                                }
                                event = parser.next();
                            }
                            mAddContactOps.add(cpoBuilder.build());
                            cpoBuilder = null;
                        } else if ("photo".equalsIgnoreCase(parser.getName().trim())) {
                            // 添加photo
                            cpoBuilder = ContentProviderOperation.newInsert(Data.CONTENT_URI)
                                    .withValue(Data.RAW_CONTACT_ID, rawContactId)
                                    .withValue(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE)
                                    .withValue(Photo.PHOTO, Base64.decodeBase64(parser.nextText()));
                            mAddContactOps.add(cpoBuilder.build());
                            cpoBuilder = null;

                        } else if ("note".equalsIgnoreCase(parser.getName().trim())) {
                            // 添加备注
                            cpoBuilder = ContentProviderOperation.newInsert(Data.CONTENT_URI)
                                    .withValue(Data.RAW_CONTACT_ID, rawContactId)
                                    .withValue(Data.MIMETYPE, Note.CONTENT_ITEM_TYPE)
                                    .withValue(Note.NOTE, parser.nextText());
                            mAddContactOps.add(cpoBuilder.build());
                            cpoBuilder = null;

                        } else {
                            String key = parser.getName().trim();
                            if (commonkindMimeTypeMap.keySet().contains(key)) {
                                buildContactUpdateContentProvider(rawContactId, parser,
                                        mAddContactOps, key);
                            }
                        }
                        break;
                    case XmlPullParser.END_TAG:
                        if ("item".equals(parser.getName()) && parser.getDepth() == 3) {
                            // 将RawContact的信息插入到ops的相应位置，commonDataKinds中的withValueBackReference参数指定值为rawIndex，则会将RawContact添加成功后的id作为RAW_CONTACT_ID的实际值
                            mAddContactOps.add(rawIndex, rawcpoBuilder.build());
                            rawcpoBuilder = null;
                            cpoBuilder = null;
                        }
                        break;
                }

                event = parser.next();
            }
            context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, mAddContactOps);
            String result = makeSuccessReplyCode("ModifyContact");
            BusinessControl.returnToClient(sc, result, context);
        } catch (Exception e) {
            e.printStackTrace();
            BusinessControl.returnToClient(sc,
                    XmlDataDealWith.getSystemErrorString(action.getName(), e.toString()), context);
            return false;
        } finally {
            parser = null;
            sr.close();
            sr = null;
            mAddContactOps.clear();

        }
        return true;
    }

    private void buildContactUpdateContentProvider(String rawContactId, XmlPullParser parser,
            ArrayList<ContentProviderOperation> ops, String commonDataKind) throws Exception {
        int event = parser.getEventType();
        // 是否有参数，仅当含有参数时才将ContentProviderOperation添加到ops里
        boolean hasParam = false;
        Builder cpoBuilder = null;
        while (!(event == XmlPullParser.END_TAG && commonDataKind.equals(parser.getName()))) {
            switch (event) {
                case XmlPullParser.START_TAG:
                    if (parser.isEmptyElementTag())
                        break;
                    if ("item".equalsIgnoreCase(parser.getName()) && parser.getDepth() == 5) {
                        cpoBuilder = ContentProviderOperation
                                .newInsert(ContactsContract.Data.CONTENT_URI)
                                .withValue(Data.RAW_CONTACT_ID, rawContactId)
                                .withValue(Data.MIMETYPE, commonkindMimeTypeMap.get(commonDataKind));

                    } else {
                        String key = parser.getName().trim();
                        HashMap<String, String> columnsMap = commonkindColumnMap
                                .get(commonDataKind);
                        if (columnsMap.containsKey(key)) {
                            cpoBuilder.withValue(columnsMap.get(key), parser.nextText());
                            hasParam = true;
                        }
                    }
                    break;
                case XmlPullParser.END_TAG:
                    if ("item".equalsIgnoreCase(parser.getName()) && parser.getDepth() == 5) {
                        if (hasParam) {
                            ops.add(cpoBuilder.build());
                        }
                        cpoBuilder = null;
                    }
                    break;
            }

            event = parser.next();
        }

    }

    /**
     * 获取联系人总数
     * 
     * @param sc
     * @param action
     * @param context
     * @return
     */
    private boolean readContactTotalHandler(SocketChannel sc, Action action, Context context) {
        Cursor c = null;
        try {
            c = context.getContentResolver().query(ContactsContract.RawContacts.CONTENT_URI, null,
                    RawContacts.DELETED + "<>1", null, null);
            int count = c.getCount();
            String result = String
                    .format("<?xml version=\"1.0\" encoding=\"utf-8\"?><root><action>ReadContactTotal</action><data><total>%d</total></data></root>",
                            count);
            BusinessControl.returnToClient(sc, result, context);
        } catch (Exception e) {
            e.printStackTrace();
            BusinessControl.returnToClient(sc,
                    XmlDataDealWith.getSystemErrorString(action.getName(), e.toString()), context);

            return false;
        } finally {
            closeCursors(c);
        }
        return true;
    }

    private static HashMap<String, String> createColumnMap(String[] tags, String[] columns) {
        HashMap<String, String> columnsMap = new HashMap<String, String>();
        int len = tags.length;
        for (int i = 0; i < len; i++) {
            columnsMap.put(tags[i], columns[i]);
        }
        return columnsMap;
    }

    /**
     * 清空联系人
     * 
     * @param sc
     * @param action
     * @param context
     * @return
     */
    private static boolean cleanupContactHandler(SocketChannel sc, Action action, Context context) {
        try {
            context.getContentResolver().delete(RawContacts.CONTENT_URI,
                    RawContacts.DELETED + "<>1", null);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        BusinessControl.returnToClient(sc, makeSuccessReplyCode("CleanupContact"), context);
        return true;
    }

    private static boolean readContactCapactiyHandler(SocketChannel sc, Action action,
            Context context) {
        String result = "<?xml version=\"1.0\" encoding=\"utf-8\"?><root><action>ReadContactCapacity</action><data><capacity>1000</capacity></data></root>";
        BusinessControl.returnToClient(sc, result, context);
        return true;
    }

    /**
     * 删除联系人并返回结果给客户端
     * 
     * @param sc
     * @param action
     * @param context
     * @return
     */
    private static boolean deleteContactOrGroupHandler(SocketChannel sc, Action action,
            Context context, Uri url) {
        String source = action.getSource();
        StringReader sr = new StringReader(source);
        XmlPullParser parser = Xml.newPullParser();
        StringBuilder whereStr = new StringBuilder();
        ArrayList<String> ids = new ArrayList<String>();
        try {
            whereStr.append(RawContacts._ID).append(" in (");
            parser.setInput(sr);
            int event = parser.getEventType();
            // 获取id列表
            while (event != XmlPullParser.END_DOCUMENT) {
                switch (event) {
                    case XmlPullParser.START_TAG:
                        if ("id".equalsIgnoreCase(parser.getName().trim())) {
                            // id为空时报错
                            if (parser.isEmptyElementTag()) {
                                BusinessControl.returnToClient(sc, XmlDataDealWith.getErrorString(
                                        action.getName(), "4",
                                        context.getResources().getString(R.string.paramIsNull_4)),
                                        context);
                                return false;
                            }

                            if (ids.size() > 0) {
                                whereStr.append(",");
                            }
                            whereStr.append("?");
                            ids.add(parser.nextText());
                        }
                        break;
                }
                event = parser.next();
            }
            whereStr.append(" )");
            // 删除id指定的联系
            context.getContentResolver().delete(url, whereStr.toString(),
                    ids.toArray(new String[] {}));
            // 返回成功字符串
            String result = makeSuccessReplyCode(action.getName());
            BusinessControl.returnToClient(sc, result, context);
        } catch (Exception e) {
            e.printStackTrace();
            BusinessControl
                    .returnToClient(sc,
                            XmlDataDealWith.getSystemErrorString(action.getName(), e.getMessage()),
                            context);
            return false;
        } finally {
            sr.close();
            sr = null;
            parser = null;
            whereStr = null;
            ids = null;
        }

        return true;
    }

    /**
     * 是否存在手机卡，GSM与CDMA机型通用
     * 
     * @param context
     * @return
     */
    private boolean isExistSIM(Context context) {
        boolean exist = false;
        TelephonyManager manager = (TelephonyManager) context
                .getSystemService(Context.TELEPHONY_SERVICE);
        int number = manager.getSimState();
        if (number != TelephonyManager.SIM_STATE_ABSENT) {
            exist = true;
        }
        return exist;
    }

    /**
     * 添加联系人
     * 
     * @param sc
     * @param action
     * @param context
     * @return
     */
    private boolean addContactHandler(SocketChannel sc, Action action, Context context) {
        ContentResolver resolver = context.getContentResolver();
        String source = action.getSource();
        StringReader sr = new StringReader(source);
        int rawIndex = 0;
        XmlPullParser parser = Xml.newPullParser();
        // 是否存在Account,存在Account_Name加1，存在Account_Type加10。和为11时两个都存在.
        int accountValue = 0;
        // 初始化accounts
        getContactAccounts(context);
        boolean existSIM = isExistSIM(context);
        try {
            parser.setInput(sr);
            int event = parser.getEventType();
            while (event != XmlPullParser.END_DOCUMENT) {
                switch (event) {
                    case XmlPullParser.START_TAG:
                        if (parser.isEmptyElementTag()) {
                            break;
                        }
                        if ("item".equals(parser.getName()) && parser.getDepth() == 3) {
                            rawIndex = mAddContactOps.size();
                            if (rawIndex >= 300) {
                                resolver.applyBatch(ContactsContract.AUTHORITY, mAddContactOps);
                                mAddContactOps.clear();
                                rawIndex = 0;
                            }
                            rawcpoBuilder = ContentProviderOperation.newInsert(
                                    RawContacts.CONTENT_URI).withValue(
                                    ContactsContract.RawContacts.AGGREGATION_MODE,
                                    ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT);
                        } else if ("source_id".equalsIgnoreCase(parser.getName())) {
                            rawcpoBuilder.withValue(RawContacts.SOURCE_ID, parser.nextText());

                        } else if ("last_contact".equalsIgnoreCase(parser.getName())) {
                            rawcpoBuilder.withValue(RawContacts.LAST_TIME_CONTACTED,
                                    parser.nextText());
                        } else if ("starred".equalsIgnoreCase(parser.getName())) {
                            rawcpoBuilder.withValue(RawContacts.STARRED, parser.nextText());
                        } else if ("account_name".equalsIgnoreCase(parser.getName())) {
                            String accountName = parser.nextText();
                            // 当手机卡不存在时，账户名为SIM或者c_contact的账户设置为空，使之保存在手机内置账户里。
                            boolean skip = false;
                            if (!existSIM) {
                                for (int i = 0; i < simNames.length; i++) {
                                    if (simNames[i].equals(accountName)) {
                                        skip = true;
                                        break;
                                    }
                                }
                            }
                            if (!skip) {
                                // 若手机中不存在该账户名，accountValue将置为0，ACCOUNT_NAME在后面会设置为NULL
                                for (Account account : accounts) {
                                    if (account.name.equals(accountName)) {
                                        accountValue += 1;
                                        rawcpoBuilder.withValue(RawContacts.ACCOUNT_NAME,
                                                accountName);
                                        break;
                                    }
                                }
                            }

                        } else if ("account_type".equalsIgnoreCase(parser.getName())) {
                            String accountType = parser.nextText();
                            // 当手机卡不存在时，账户名为SIM或者c_contact的账户设置为空，使之保存在手机内置账户里。
                            boolean skip = false;
                            if (!existSIM) {
                                for (int i = 0; i < simTypes.length; i++) {
                                    if (simTypes[i].equals(accountType)) {
                                        skip = true;
                                        break;
                                    }
                                }
                            }
                            if (!skip) {
                                // 若手机中不存在该账户类型，accountValue将置为0，ACCOUNT_TYPE在后面会设置为NULL
                                for (Account account : accounts) {
                                    if (account.type.equals(accountType)) {
                                        accountValue += 10;
                                        rawcpoBuilder.withValue(RawContacts.ACCOUNT_TYPE,
                                                accountType);
                                        break;
                                    }
                                }
                            }
                        } else if ("structuredName".equalsIgnoreCase(parser.getName())) {
                            cpoBuilder = ContentProviderOperation
                                    .newInsert(ContactsContract.Data.CONTENT_URI)
                                    .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID,
                                            rawIndex)
                                    .withValue(
                                            ContactsContract.Data.MIMETYPE,
                                            ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
                            while (!(event == XmlPullParser.END_TAG && "structuredName"
                                    .equals(parser.getName()))) {
                                switch (event) {
                                    case XmlPullParser.START_TAG:
                                        if ("display_name".equalsIgnoreCase(parser.getName())) {
                                            cpoBuilder.withValue(StructuredName.DISPLAY_NAME,
                                                    parser.nextText());
                                        } else if ("given_name".equalsIgnoreCase(parser.getName())) {
                                            cpoBuilder.withValue(StructuredName.GIVEN_NAME,
                                                    parser.nextText());
                                        } else if ("family_name".equalsIgnoreCase(parser.getName())) {
                                            cpoBuilder.withValue(StructuredName.FAMILY_NAME,
                                                    parser.nextText());
                                        } else if ("middle_name".equalsIgnoreCase(parser.getName())) {
                                            cpoBuilder.withValue(StructuredName.MIDDLE_NAME,
                                                    parser.nextText());
                                        }
                                        break;
                                }
                                event = parser.next();
                            }
                            mAddContactOps.add(cpoBuilder.build());
                            cpoBuilder = null;
                        } else if ("photo".equalsIgnoreCase(parser.getName().trim())) {
                            // 添加photo
                            cpoBuilder = ContentProviderOperation.newInsert(Data.CONTENT_URI)
                                    .withValueBackReference(Data.RAW_CONTACT_ID, rawIndex)
                                    .withValue(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE)
                                    .withValue(Photo.PHOTO, Base64.decodeBase64(parser.nextText()));
                            mAddContactOps.add(cpoBuilder.build());
                            cpoBuilder = null;

                        } else if ("note".equalsIgnoreCase(parser.getName().trim())) {
                            // 添加备注
                            cpoBuilder = ContentProviderOperation.newInsert(Data.CONTENT_URI)
                                    .withValueBackReference(Data.RAW_CONTACT_ID, rawIndex)
                                    .withValue(Data.MIMETYPE, Note.CONTENT_ITEM_TYPE)
                                    .withValue(Note.NOTE, parser.nextText());
                            mAddContactOps.add(cpoBuilder.build());
                            cpoBuilder = null;

                        } else {
                            String key = parser.getName().trim();
                            if (commonkindMimeTypeMap.keySet().contains(key)) {
                                buildContactInsertContentProvider(rawIndex, parser, mAddContactOps,
                                        key);
                            }
                        }
                        break;
                    case XmlPullParser.END_TAG:
                        if ("item".equals(parser.getName()) && parser.getDepth() == 3) {
                            // 若没有指定账户名，则设置为null
                            if (accountValue == 0) {
                                rawcpoBuilder.withValue(RawContacts.ACCOUNT_NAME, null);
                                rawcpoBuilder.withValue(RawContacts.ACCOUNT_TYPE, null);
                            } else if (accountValue != 11) {
                                BusinessControl.returnToClient(sc, XmlDataDealWith.getErrorString(
                                        action.getName(), "4",
                                        context.getResources().getString(R.string.paramIsNull_4)),
                                        context);
                                return false;
                            }
                            // 将RawContact的信息插入到ops的相应位置，commonDataKinds中的withValueBackReference参数指定值为rawIndex，则会将RawContact添加成功后的id作为RAW_CONTACT_ID的实际值
                            mAddContactOps.add(rawIndex, rawcpoBuilder.build());
                            accountValue = 0;
                            rawcpoBuilder = null;
                            cpoBuilder = null;
                        }
                        break;
                }

                event = parser.next();
            }
            ContentProviderResult[] results = context.getContentResolver().applyBatch(
                    ContactsContract.AUTHORITY, mAddContactOps);
            ArrayList<String> idsArray = new ArrayList<String>();
            for (int i = 0; i < results.length; i++) {
                Uri uri = results[i].uri;
                if ("raw_contacts".equals(uri.getPathSegments().get(0))) {
                    idsArray.add(uri.getLastPathSegment());
                }
            }
            String[] ids = new String[idsArray.size()];
            ids = idsArray.toArray(ids);
            String result = makeAddSuccessReplyCode(action, ids);
            BusinessControl.returnToClient(sc, result, context);
        } catch (Exception e) {
            e.printStackTrace();
            BusinessControl.returnToClient(sc,
                    XmlDataDealWith.getSystemErrorString(action.getName(), e.toString()), context);
            return false;
        } finally {
            parser = null;
            sr.close();
            sr = null;
            mAddContactOps.clear();

        }
        return true;
    }

    /**
     * 构建添加成功后的返回字符串，用于AddContact及AddContactGroup命令
     * 
     * @param action
     * @param ids 添加成功后的id数组
     * @return
     */
    private String makeAddSuccessReplyCode(Action action, String[] ids) throws Exception {
        StringWriter writer = new StringWriter();
        XmlSerializer serializer = Xml.newSerializer();

        serializer.setOutput(writer);
        XmlDataDealWith.createPre(action, serializer);
        for (String id : ids) {
            serializer.startTag("", "item");
            writeSingleTextToXml(serializer, "id", id);
            serializer.endTag("", "item");
        }
        serializer.endTag("", "data");
        serializer.endTag("", "root");
        serializer.endDocument();

        return writer.toString();
    }

    /**
     * 构建ContactsContract.CommonDataKinds类型的ContentProviderOperation，
     * 并添加到ops中以实现批量操作数据库
     * 
     * @param parser Xml解析器
     * @param ops ContentProviderOperation的集合，用于批量操作数据库
     * @param commonDataKind xml文件中的类型名,如phone,email等
     * @param columnsMap xml文件中的列名与数据库中的列名的对应map集合，以xml文件的列名为key
     * @param mimeType ContactsContract.CommonDataKinds的mimeType
     * @throws Exception
     */
    private static void buildContactInsertContentProvider(int index, XmlPullParser parser,
            ArrayList<ContentProviderOperation> ops, String commonDataKind) throws Exception {
        int event = parser.getEventType();
        // 是否有参数，仅当含有参数时才将ContentProviderOperation添加到ops里
        boolean hasParam = false;
        Builder cpoBuilder = null;
        while (!(event == XmlPullParser.END_TAG && commonDataKind.equals(parser.getName()))) {
            switch (event) {
                case XmlPullParser.START_TAG:
                    if (parser.isEmptyElementTag())
                        break;
                    if ("item".equalsIgnoreCase(parser.getName()) && parser.getDepth() == 5) {
                        cpoBuilder = ContentProviderOperation
                                .newInsert(ContactsContract.Data.CONTENT_URI)
                                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, index)
                                .withValue(ContactsContract.Data.MIMETYPE,
                                        commonkindMimeTypeMap.get(commonDataKind));
                    } else {
                        String key = parser.getName().trim();
                        HashMap<String, String> columnsMap = commonkindColumnMap
                                .get(commonDataKind);
                        if (columnsMap.containsKey(key)) {
                            cpoBuilder.withValue(columnsMap.get(key), parser.nextText());
                            hasParam = true;
                        }
                    }
                    break;
                case XmlPullParser.END_TAG:
                    if ("item".equalsIgnoreCase(parser.getName()) && parser.getDepth() == 5) {
                        if (hasParam) {
                            ops.add(cpoBuilder.build());
                        }
                        cpoBuilder = null;
                    }
                    break;
            }

            event = parser.next();
        }

    }

    /**
     * 获取手机内与联系人相关的账户
     * 
     * @param context
     * @return
     */
    public List<Account> getContactAccounts(Context context) {
        if (accounts == null) {
            accounts = new ArrayList<Account>();
            Cursor accountCursor = context.getContentResolver().query(
                    ContactsContract.Settings.CONTENT_URI,
                    new String[] {
                            ContactsContract.Settings.ACCOUNT_NAME,
                            ContactsContract.Settings.ACCOUNT_TYPE
                    }, null, null, null);
            while (accountCursor.moveToNext()) {
                String name = accountCursor.getString(accountCursor
                        .getColumnIndex(ContactsContract.Settings.ACCOUNT_NAME));
                String type = accountCursor.getString(accountCursor
                        .getColumnIndex(ContactsContract.Settings.ACCOUNT_TYPE));
                accounts.add(new Account(name, type));
            }
            accountCursor.close();
        }
        return accounts;
    }

    private static String[] rawContactColumns = new String[] {
            RawContacts._ID, RawContacts.SOURCE_ID, RawContacts.LAST_TIME_CONTACTED,
            RawContacts.STARRED, RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_TYPE
    };

    private static String[] structuredNameColumns = new String[] {
            StructuredName.DISPLAY_NAME, StructuredName.GIVEN_NAME, StructuredName.FAMILY_NAME,
            StructuredName.MIDDLE_NAME
    };

    private static String[] nicknameColumns = new String[] {
        Nickname.NAME
    };

    private static String[] photoColumns = new String[] {
        Photo.PHOTO
    };

    private static String[] phoneColumns = new String[] {
            Phone.TYPE, Phone.NUMBER, Phone.LABEL, Phone.IS_PRIMARY
    };

    private static String[] emailColumns = new String[] {
            Email.DATA, Email.TYPE, Email.LABEL
    };

    private static String[] imColumns = new String[] {
            Im.DATA, Im.TYPE, Im.LABEL, Im.PROTOCOL, Im.CUSTOM_PROTOCOL
    };

    private static String[] eventColumns = new String[] {
            Event.START_DATE, Event.TYPE, Event.LABEL
    };

    private static String[] organizationColumns = new String[] {
            Organization.COMPANY, Organization.TYPE, Organization.LABEL, Organization.TITLE
    };

    private static String[] groupMemberColumns = new String[] {
        GroupMembership.GROUP_ROW_ID
    };

    private static String[] structuredPostalColumns = new String[] {
            StructuredPostal.FORMATTED_ADDRESS, StructuredPostal.TYPE, StructuredPostal.LABEL,
            StructuredPostal.STREET, StructuredPostal.POBOX, StructuredPostal.NEIGHBORHOOD,
            StructuredPostal.CITY, StructuredPostal.REGION, StructuredPostal.POSTCODE,
            StructuredPostal.COUNTRY
    };

    private static final String[] relationColumns = new String[] {
            Relation.NAME, Relation.TYPE, Relation.LABEL
    };

    private static final String[] websiteColumns = new String[] {
            Website.URL, Website.TYPE, Website.LABEL,
    };

    private static final String[] noteColumns = new String[] {
        Note.NOTE
    };

    private static final String[] nicknameTags = new String[] {
        "name"
    };

    private static final String[] phoneTags = new String[] {
            "type", "number", "label", "isPrimary"
    };

    private static final String[] emailTags = new String[] {
            "data", "type", "label"
    };

    private static final String[] imTags = new String[] {
            "data", "type", "label", "protocol", "custom_protocol"
    };

    private static final String[] eventTags = new String[] {
            "start_date", "type", "label"
    };

    private static final String[] organizationTags = new String[] {
            "company", "type", "label", "title"
    };

    private static final String[] groupMemberTags = new String[] {
        "groupID"
    };

    private static final String[] structuredPostalTags = new String[] {
            "formatted_address", "type", "label", "street", "pobox", "neighborhood", "city",
            "region", "postcode", "country"
    };

    private static final String[] relationTags = new String[] {
            "name", "type", "label"
    };

    private static final String[] websiteTags = new String[] {
            "url", "type", "label"
    };

    /**
     * 获取联系人信息发送到PC端
     * 
     * @throws XmlPullParserException
     */
    private static boolean loadContactHandler(SocketChannel sc, Action action, Context context) {
        StringWriter writer = null;
        Cursor commonkindCursor = null;
        XmlSerializer serializer = null;
        Cursor rawContactCursor = null;
        try {

            // 起始索引
            int from = Integer.parseInt(action.getFrom());
            // 结束索引
            int to = Integer.parseInt(action.getTo());
            // 解析是否带有id参数
            StringBuilder whereStr = new StringBuilder();
            whereStr.append(RawContacts.DELETED + "<>1");
            LinkedList<String> ids = XmlDataDealWith.getRegular("id", action.getSource());
            if (ids.size() > 0) {
                whereStr.append(" and ").append(RawContacts._ID).append(" in (");
                for (int i = 0; i < ids.size(); i++) {

                    whereStr.append("?,");
                }
                whereStr.deleteCharAt(whereStr.lastIndexOf(",")).append(")");
            }
            Uri rawContactUri = RawContacts.CONTENT_URI;
            rawContactCursor = context.getContentResolver().query(rawContactUri, rawContactColumns,
                    whereStr.toString(), ids.size() > 0 ? ids.toArray(new String[] {}) : null,
                    RawContacts._ID);
            // 结果总记录数
            int total = rawContactCursor.getCount();

            if (from <= 0 || to <= 0 || to < from || from > total
                    || !rawContactCursor.moveToPosition(from - 1)) {
                BusinessControl.returnToClient(sc, makeNullLoadContactReplyCode(0, 0, total),
                        context);
                return true;
            }
            writer = new StringWriter();
            serializer = Xml.newSerializer();
            serializer.setOutput(writer);
            XmlDataDealWith.createPre(action, serializer);
            while (rawContactCursor.getPosition() < to) {
                serializer.startTag(null, "item");
                String rawID = getCursorString(rawContactCursor, RawContacts._ID);
                writeSingleCursorDataToXml(serializer, rawContactCursor, "id", RawContacts._ID);
                writeSingleCursorDataToXml(serializer, rawContactCursor, "source_id",
                        RawContacts.SOURCE_ID);
                writeSingleCursorDataToXml(serializer, rawContactCursor, "last_contact",
                        RawContacts.LAST_TIME_CONTACTED);
                writeSingleCursorDataToXml(serializer, rawContactCursor, "starred",
                        RawContacts.STARRED);
                writeSingleCursorDataToXml(serializer, rawContactCursor, "account_name",
                        RawContacts.ACCOUNT_NAME);
                writeSingleCursorDataToXml(serializer, rawContactCursor, "account_type",
                        RawContacts.ACCOUNT_TYPE);

                // 设置structuredName
                commonkindCursor = createContactCursor(context, Data.CONTENT_URI,
                        structuredNameColumns, rawID, StructuredName.CONTENT_ITEM_TYPE);
                serializer.startTag(null, "structuredName");
                if (commonkindCursor.moveToFirst()) {
                    writeSingleCursorDataToXml(serializer, commonkindCursor, "display_name",
                            StructuredName.DISPLAY_NAME);
                    writeSingleCursorDataToXml(serializer, commonkindCursor, "given_name",
                            StructuredName.GIVEN_NAME);
                    writeSingleCursorDataToXml(serializer, commonkindCursor, "family_name",
                            StructuredName.FAMILY_NAME);
                    writeSingleCursorDataToXml(serializer, commonkindCursor, "middle_name",
                            StructuredName.MIDDLE_NAME);
                }
                serializer.endTag(null, "structuredName");
                commonkindCursor.close();
                // 设置nickname
                commonkindCursor = createContactCursor(context, Data.CONTENT_URI, nicknameColumns,
                        rawID, Nickname.CONTENT_ITEM_TYPE);
                writeMultiContactDataToXml(serializer, "nickname", commonkindCursor, nicknameTags,
                        nicknameColumns);

                // 设置photo
                commonkindCursor = createContactCursor(context, Data.CONTENT_URI, photoColumns,
                        rawID, Photo.CONTENT_ITEM_TYPE);
                String photoStr = "";
                if (commonkindCursor.moveToFirst()) {
                    byte[] photoBlob = commonkindCursor.getBlob(commonkindCursor
                            .getColumnIndex(Photo.PHOTO));
                    if (photoBlob != null) {
                        photoStr = Base64.encodeBase64String(photoBlob);
                    }
                }
                serializer.startTag(null, "photo");
                serializer.text(photoStr);
                serializer.endTag(null, "photo");
                commonkindCursor.close();

                // 设置Phone
                commonkindCursor = createContactCursor(context, Phone.CONTENT_URI, phoneColumns,
                        rawID);

                writeMultiContactDataToXml(serializer, "phone", commonkindCursor, phoneTags,
                        phoneColumns);

                // 设置email

                commonkindCursor = createContactCursor(context, Data.CONTENT_URI, emailColumns,
                        rawID, Email.CONTENT_ITEM_TYPE);
                writeMultiContactDataToXml(serializer, "email", commonkindCursor, emailTags,
                        emailColumns);

                // 设置IM

                commonkindCursor = createContactCursor(context, Data.CONTENT_URI, imColumns, rawID,
                        Im.CONTENT_ITEM_TYPE);
                writeMultiContactDataToXml(serializer, "im", commonkindCursor, imTags, imColumns);

                // 设置event

                commonkindCursor = createContactCursor(context, Data.CONTENT_URI, eventColumns,
                        rawID, Event.CONTENT_ITEM_TYPE);
                writeMultiContactDataToXml(serializer, "event", commonkindCursor, eventTags,
                        eventColumns);

                // 设置organization

                commonkindCursor = createContactCursor(context, Data.CONTENT_URI,
                        organizationColumns, rawID, Organization.CONTENT_ITEM_TYPE);
                writeMultiContactDataToXml(serializer, "organization", commonkindCursor,
                        organizationTags, organizationColumns);

                // 设置groupMember

                commonkindCursor = createContactCursor(context, Data.CONTENT_URI,
                        groupMemberColumns, rawID, GroupMembership.CONTENT_ITEM_TYPE);
                writeMultiContactDataToXml(serializer, "groupMember", commonkindCursor,
                        groupMemberTags, groupMemberColumns);

                // 设置structuredPostal

                commonkindCursor = createContactCursor(context, StructuredPostal.CONTENT_URI,
                        structuredPostalColumns, rawID);
                writeMultiContactDataToXml(serializer, "structuredPostal", commonkindCursor,
                        structuredPostalTags, structuredPostalColumns);

                // 设置relation

                commonkindCursor = createContactCursor(context, Data.CONTENT_URI, relationColumns,
                        rawID, Relation.CONTENT_ITEM_TYPE);
                writeMultiContactDataToXml(serializer, "relation", commonkindCursor, relationTags,
                        relationColumns);

                // 设置SipAddress ，android2.1版本无此属性，故只设置为空
                serializer.startTag(null, "SipAddress");
                serializer.endTag(null, "SipAddress");

                // 设置website

                commonkindCursor = createContactCursor(context, Data.CONTENT_URI, websiteColumns,
                        rawID, Website.CONTENT_ITEM_TYPE);
                writeMultiContactDataToXml(serializer, "website", commonkindCursor, websiteTags,
                        websiteColumns);

                // 设置note
                commonkindCursor = createContactCursor(context, Data.CONTENT_URI, noteColumns,
                        rawID, Note.CONTENT_ITEM_TYPE);
                serializer.startTag(null, "note");
                String note = "";
                if (commonkindCursor.moveToFirst()) {
                    note = commonkindCursor.getString(commonkindCursor.getColumnIndex(Note.NOTE));
                    if (note == null) {
                        note = "";
                    }
                }
                serializer.text(note);
                serializer.endTag(null, "note");
                commonkindCursor.close();

                serializer.endTag(null, "item");
                if (!rawContactCursor.moveToNext()) {
                    break;
                }
            }
            to = rawContactCursor.getPosition();
            serializer.text("");
            serializer.endTag("", "data");

            writeSingleTextToXml(serializer, "from", "" + from);
            writeSingleTextToXml(serializer, "to", "" + to);
            writeSingleTextToXml(serializer, "total", "" + total);

            serializer.endTag("", "root");
            serializer.endDocument();
            BusinessControl.returnToClient(sc, writer.toString(), context);
        } catch (Exception e) {
            e.printStackTrace();
            BusinessControl
                    .returnToClient(sc,
                            XmlDataDealWith.getSystemErrorString(action.getName(), e.getMessage()),
                            context);
            return false;
        } finally {
            closeCursors(rawContactCursor);
            serializer = null;
            try {
                if (writer != null) {
                    writer.close();
                    writer = null;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

        return true;
    }

    private boolean loadContactGroupHandler(SocketChannel sc, Action action, Context context) {
        StringWriter writer = new StringWriter();
        Cursor cursor = null;
        XmlSerializer serializer = Xml.newSerializer();
        Cursor summaryCursor = null;
        try {
            serializer.setOutput(writer);
            XmlDataDealWith.createPre(action, serializer);

            cursor = context.getContentResolver().query(Groups.CONTENT_URI, groupProjection,
                    Groups.DELETED + "<> 1", null, Groups.TITLE);
            while (cursor.moveToNext()) {
                serializer.startTag("", "item");
                long id = cursor.getLong(cursor.getColumnIndex(Groups._ID));
                writeSingleTextToXml(serializer, "id", String.valueOf(id));
                writeSingleCursorDataToXml(serializer, cursor, "title", Groups.TITLE);
                summaryCursor = context.getContentResolver().query(Groups.CONTENT_SUMMARY_URI,
                        groupSummaryProjection, Groups._ID + "=" + id, null, null);
                if (summaryCursor.moveToFirst()) {
                    writeSingleCursorDataToXml(serializer, summaryCursor, "summary_count",
                            Groups.SUMMARY_COUNT);
                }
                summaryCursor.close();
                summaryCursor = null;
                serializer.endTag("", "item");
            }
            if (cursor.getCount() <= 0) {
                serializer.text("");
            }
            serializer.endTag("", "data");
            serializer.endTag("", "root");
            serializer.endDocument();

            BusinessControl.returnToClient(sc, writer.toString(), context);
        } catch (Exception e) {
            e.printStackTrace();
            BusinessControl
                    .returnToClient(sc,
                            XmlDataDealWith.getSystemErrorString(action.getName(), e.getMessage()),
                            context);
            return false;

        } finally {
            closeCursors(cursor);
            serializer = null;
            try {
                if (writer != null)
                    writer.close();
                writer = null;
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
        return true;
    }

    private boolean modifyContactGroupHandler(SocketChannel sc, Action action, Context context) {
        ContentResolver resolver = context.getContentResolver();
        String source = action.getSource();
        StringReader sr = new StringReader(source);
        XmlPullParser parser = Xml.newPullParser();
        ContentValues values = new ContentValues();
        String id = null;
        try {
            parser.setInput(sr);
            int event = parser.getEventType();
            while (event != XmlPullParser.END_DOCUMENT) {
                switch (event) {
                    case XmlPullParser.START_TAG:

                        if ("item".equals(parser.getName().trim()) && parser.getDepth() == 3) {
                            values.clear();
                        } else if ("id".equalsIgnoreCase(parser.getName().trim())) {
                            if (parser.isEmptyElementTag()) {
                                BusinessControl.returnToClient(sc, XmlDataDealWith.getErrorString(
                                        action.getName(), "4",
                                        context.getResources().getString(R.string.paramIsNull_4)),
                                        context);
                                return false;
                            }
                            id = parser.nextText();

                        } else if ("title".equalsIgnoreCase(parser.getName().trim())) {
                            if (parser.isEmptyElementTag()) {
                                BusinessControl.returnToClient(sc, XmlDataDealWith.getErrorString(
                                        action.getName(), "4",
                                        context.getResources().getString(R.string.paramIsNull_4)),
                                        context);
                                return false;
                            }
                            values.put(Groups.TITLE, parser.nextText());
                        }
                        break;
                    case XmlPullParser.END_TAG:
                        if ("item".equals(parser.getName().trim()) && parser.getDepth() == 3) {
                            resolver.update(Groups.CONTENT_URI, values, Groups._ID + "=" + id, null);
                        }
                        break;
                }
                event = parser.next();
            }
            BusinessControl.returnToClient(sc, makeSuccessReplyCode(action.getName()), context);
        } catch (Exception e) {
            e.printStackTrace();
            BusinessControl
                    .returnToClient(sc,
                            XmlDataDealWith.getSystemErrorString(action.getName(), e.getMessage()),
                            context);
            return false;
        } finally {
            sr.close();
            sr = null;
            parser = null;
        }
        return true;
    }

    private boolean addContactGroupHandler(SocketChannel sc, Action action, Context context) {
        ContentResolver resolver = context.getContentResolver();
        String source = action.getSource();
        StringReader sr = new StringReader(source);
        XmlPullParser parser = Xml.newPullParser();
        ContentValues values = new ContentValues();
        ArrayList<String> idsArray = new ArrayList<String>();
        try {
            parser.setInput(sr);
            int event = parser.getEventType();
            while (event != XmlPullParser.END_DOCUMENT) {
                switch (event) {
                    case XmlPullParser.START_TAG:
                        if (parser.isEmptyElementTag()) {
                            break;
                        }
                        if ("item".equals(parser.getName().trim()) && parser.getDepth() == 3) {
                            values.clear();
                        } else if ("title".equalsIgnoreCase(parser.getName().trim())) {
                            values.put(Groups.TITLE, parser.nextText());
                        }
                        break;
                    case XmlPullParser.END_TAG:
                        if ("item".equals(parser.getName().trim()) && parser.getDepth() == 3) {
                            Uri uri = resolver.insert(Groups.CONTENT_URI, values);
                            idsArray.add(uri.getLastPathSegment());
                        }
                        break;
                }
                event = parser.next();
            }
            String[] ids = new String[idsArray.size()];
            for (int i = 0; i < ids.length; i++) {
                ids[i] = idsArray.get(i);
            }
            BusinessControl.returnToClient(sc, makeAddSuccessReplyCode(action, ids), context);
        } catch (Exception e) {
            e.printStackTrace();
            BusinessControl
                    .returnToClient(sc,
                            XmlDataDealWith.getSystemErrorString(action.getName(), e.getMessage()),
                            context);
            return false;
        } finally {
            sr.close();
            sr = null;
            parser = null;
        }
        return true;
    }

    // private static void writeCommonkindsToXml(Context context, XmlSerializer
    // serializer,
    // String rawID) throws IllegalArgumentException, IllegalStateException,
    // IOException {
    // String where = Data.RAW_CONTACT_ID + " =? and " + Data.MIMETYPE + " = ?";
    // String commonkind = null;
    // String contentItemType = null;
    // Cursor commonkindC = null;
    // for (int i = 0; i < commonkinds.length; i++) {
    //
    // commonkind = commonkinds[i];
    // contentItemType = commonkindMimeTypeMap.get(commonkind);
    //
    // commonkindC = context.getContentResolver().query(Data.CONTENT_URI,
    // commonkindColumnMap.get(commonkind).values().toArray(new String[] {}),
    // where,
    // new String[] {
    // rawID, contentItemType
    // }, null);
    // writeMultiContactDataToXml(serializer, commonkind, commonkindC);
    // closeCursors(commonkindC);
    // }
    //
    // }

    // private static void writeMultiContactDataToXml(XmlSerializer serializer,
    // String commonkind,
    // Cursor dataCursor) throws IllegalArgumentException,
    // IllegalStateException, IOException {
    // serializer.startTag(null, commonkind);
    // HashMap<String, String> columnMap = commonkindColumnMap.get(commonkind);
    // while (dataCursor.moveToNext()) {
    // serializer.startTag(null, "item");
    // for (String key : columnMap.keySet()) {
    // writeSingleCursorDataToXml(serializer, dataCursor, key,
    // columnMap.get(key));
    // }
    // serializer.endTag(null, "item");
    // }
    // serializer.endTag(null, commonkind);
    //
    // }

    private static String makeNullLoadContactReplyCode(int from, int to, int total) {
        return String
                .format("<?xml version=\"1.0\" encoding=\"utf-8\"?><root><action>LoadContact</action><data/><from>%d</from><to>%d</to><total>%d</total></root>",
                        from, to, total);
    }

    /**
     * 生成无实际返回数据的操作的成功返回代码，如addContact和deleteContact
     * 
     * @param action
     * @return <?xml version="1.0"
     *         encoding="utf-8"?><root><action>action</action></root>
     */
    private static String makeSuccessReplyCode(String action) {
        return String.format(
                "<?xml version=\"1.0\" encoding=\"utf-8\"?><root><action>%s</action></root>",
                action);
    }

    /**
     * 根据条件创建联系人的Cursor
     * 
     * @param context
     * @param contactDataUri CommonDataKinds的Uri
     * @param columnNames 列名
     * @param rawID RawContacts的id
     * @param contentItemType CommonDataKinds的类型
     * @return
     */
    private static Cursor createContactCursor(Context context, Uri contactDataUri,
            String[] columnNames, String rawID, String contentItemType) {
        StringBuilder where = new StringBuilder();
        ArrayList<String> whereList = new ArrayList<String>();

        if (rawID != null && !"".equals(rawID)) {
            where.append(Data.RAW_CONTACT_ID).append(" =?");
            whereList.add(rawID);
        }
        if (contentItemType != null && !"".equals(contentItemType)) {
            if (whereList.size() > 0) {
                where.append(" and ");
            }
            where.append(Data.MIMETYPE).append(" = ?");
            whereList.add(contentItemType);
        }
        return context.getContentResolver().query(contactDataUri, columnNames, where.toString(),
                whereList.toArray(new String[] {}), null);

    }

    private static Cursor createContactCursor(Context context, Uri contactDataUri,
            String[] columnNames, String rawID) {

        return createContactCursor(context, contactDataUri, columnNames, rawID, null);
    }

    /**
     * 将一个包含多个节点属性的对象写入XML，如<root><"item"><key1>value1</key1><key2>value2<key2><
     * / "item"><"item">...</"item"></root>
     * 
     * @param serializer
     * @param root
     * @param dataCursor
     * @param data
     * @throws IllegalArgumentException
     * @throws IllegalStateException
     * @throws IOException
     */
    private static void writeMultiContactDataToXml(XmlSerializer serializer, String root,
            Cursor dataCursor, String[] tags, String[] columnNames)
            throws IllegalArgumentException, IllegalStateException, IOException {
        serializer.startTag(null, root);
        while (dataCursor.moveToNext()) {
            serializer.startTag(null, "item");
            int len = tags.length;
            for (int i = 0; i < len; i++) {
                writeSingleCursorDataToXml(serializer, dataCursor, tags[i], columnNames[i]);
            }
            serializer.endTag(null, "item");
        }
        serializer.endTag(null, root);
        closeCursors(dataCursor);
    }

    private static void closeCursors(Cursor... cursors) {
        for (Cursor cursor : cursors) {
            if (cursor != null) {
                cursor.close();
                cursor = null;
            }
        }

    }

    /**
     * 创建一个包含单个值的XML节点，如<TAG>value</TAG>,写入serializer中
     * 
     * @param serializer xml写入器
     * @param cursor 联系人的cursor
     * @param tag 节点名
     * @param columnName 联系人数据库的列名
     * @throws IllegalArgumentException
     * @throws IllegalStateException
     * @throws IOException
     */
    private static void writeSingleCursorDataToXml(XmlSerializer serializer, Cursor cursor,
            String tag, String columnName) throws IllegalArgumentException, IllegalStateException,
            IOException {
        String value = getCursorString(cursor, columnName);
        if (value == null)
            value = "";
        serializer.startTag(null, tag);
        // 值为空时不写入XML

        serializer.text(value);

        serializer.endTag(null, tag);
    }

    /**
     * 创建一个包含单个值的XML节点，如<TAG>value</TAG>,写入serializer中
     * 
     * @param serializer xml写入器
     * @param tag 节点名
     * @param value 节点值
     * @throws IllegalArgumentException
     * @throws IllegalStateException
     * @throws IOException
     */
    private static void writeSingleTextToXml(XmlSerializer serializer, String tag, String value)
            throws IllegalArgumentException, IllegalStateException, IOException {
        // 值为空时不写入XML
        if (value == null)
            value = "";
        serializer.startTag(null, tag);
        serializer.text(value);
        serializer.endTag(null, tag);
    }

    /**
     * 获取Cursor中指定列的值
     * 
     * @param cursor
     * @param columnName 列名
     * @return 返回值为String类型
     */
    private static String getCursorString(Cursor cursor, String columnName) {
        return cursor.getString(cursor.getColumnIndex(columnName));
    }
}
